package de.codi.string;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import de.codi.CODISettings;


public class StringPreparation
{

    private static Set<String>             switches;
    private static Set<String>             remove;
    private static Set<String>             removePlus;

    private static final StringPreparation SESSION = new StringPreparation();


    private StringPreparation()
    {
        switches = new HashSet<String>();
        remove = new HashSet<String>();
        removePlus = new HashSet<String>();

        BufferedReader inS, inR, inRP;
        try {
            String zeile = null;

            inS = new BufferedReader(new FileReader(CODISettings.PATH + "res/stopwords/switch.txt"));
            while((zeile = inS.readLine()) != null) {
                switches.add(zeile);
            }

            inR = new BufferedReader(new FileReader(CODISettings.PATH + "res/stopwords/remove.txt"));
            while((zeile = inR.readLine()) != null) {
                remove.add(zeile);
            }

            inRP = new BufferedReader(new FileReader(CODISettings.PATH + "res/stopwords/remove_plus.txt"));
            while((zeile = inRP.readLine()) != null) {
                removePlus.add(zeile);
            }

            inS.close();
            inR.close();
            inRP.close();
        } catch(IOException e) {
            e.printStackTrace();
        }
    }


    public StringPreparation getSession()
    {
        return SESSION;
    }


    public static String standardize(String s)
    {
        String[] values = { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" };

        if(s == null || s.equals(""))
            return "";

        String temp = "", result = "";

        for(String c : values) {
            if(s.substring(1).contains(c)) {
                s = s.substring(0, s.indexOf(c)) + " " + s.substring(s.indexOf(c));
            }
        }

        temp = s.replaceAll("_", " ");
        temp = temp.replaceAll("-", "");
        temp = temp.replaceAll("[(]", "");
        temp = temp.replaceAll("[)]", "");
        temp = temp.replaceAll("[/]", " ");

        result += temp.charAt(0);

        for(int i = 1; i < temp.length(); i++) {
            boolean isNumber = false;
            boolean isPrevNumber = false;
            if(Character.isUpperCase(temp.charAt(i)) && temp.charAt(i - 1) != ' ') {
                result += " ";

            }
            // if temp[i] is a number and temp[i-1] is not, add "" (e.g. c-12345-9876 => c 123459876)
            isNumber = !isNotNumber(Character.toString(temp.charAt(i)));
            isPrevNumber = isNotNumber(Character.toString(temp.charAt(i - 1)));
            if(isNumber && isPrevNumber) {
                result += " ";
            }

            result += temp.charAt(i);
        }

        result = result.toLowerCase().replaceAll("  ", " ");
        while(result.contains("  ")) {
            result = result.replace("  ", " ");
        }
        result = stopWords(result);

        return result.trim();
    }


    public static String stopWords(String s)
    {
        String result = new String(s);

        // for(String v : switches)
        // {
        // while(result.contains(" "+v+" ")) // TODO
        // {
        // result=result.substring(result.indexOf(v)+2).trim()+" "+result.substring(0,result.indexOf(v)).trim();
        // }
        // }

        for(String v : remove) {
            if(result.contains(" " + v + " ")) {
                result = result.replace(" " + v + " ", " ");
            }
        }

        return result;
    }


    public static List<String> shortCut(String a, String b)
    {
        // System.out.println(a +" - "+ b);
        Set<Integer> position = new HashSet<Integer>();
        List<String> result = new ArrayList<String>();

        String[] wordA = a.split(" ");
        String[] wordB = b.split(" ");

        HashSet<Integer> stop = new HashSet<Integer>();

        // find single letters
        for(int i = 0; i < wordA.length; i++) {
            if(wordA[i].length() == 1 && isNotNumber(wordA[i])) {
                position.add(i);
            }
        }

        // a.length = b.length + single letter
        if(wordA.length == wordB.length && position.size() > 0) {
            int count = 0;
            // every single letter (in a)
            for(int i : position) {
                for(int j = 0; j < wordB.length; j++) {
                    if(stop.contains(j) || wordB[j].length() == 0)
                        continue;
                    // short cut? -> equals
                    if(wordA[i].equals(wordB[j].substring(0, 1))) {
                        wordA[i] = wordB[j];
                        count++;
                        stop.add(j);
                        break;
                    }
                }
            }

            // complete?
            if(count == position.size()) {
                // equal complete words
                for(int x = 0; x < wordA.length; x++) {
                    for(int y = 0; y < wordB.length; y++) {
                        if(wordB[y].equals(wordA[x]) && !stop.contains(y)) {
                            position.add(x);
                            break;
                        }
                    }
                }
                // complete -> equals
                if(wordB.length == position.size()) {
                    a = b;
                }
            }
        }

        position = new HashSet<Integer>(); // reset
        stop.clear();

        for(int i = 0; i < wordB.length; i++) {
            if(wordB[i].length() == 1 && isNotNumber(wordB[i])) {
                position.add(i);
            }
        }

        if(wordA.length == wordB.length && position.size() > 0) {
            int count = 0;
            for(int i : position) {
                for(int j = 0; j < wordA.length; j++) {
                    if(stop.contains(j) || wordA[j].length() == 0)
                        continue;
                    if(wordB[i].equals(wordA[j].substring(0, 1))) {
                        wordB[i] = wordA[j];
                        count++;
                        stop.add(j);
                        break;
                    }
                }
            }

            if(count == position.size()) {
                for(int x = 0; x < wordB.length; x++) {
                    for(int y = 0; y < wordA.length; y++) {
                        if(wordA[y].equals(wordB[x]) && !stop.contains(y)) {
                            position.add(x);
                            break;
                        }
                    }
                }
                if(wordA.length == position.size()) {
                    b = a;
                }
            }
        }

        result.add(a);
        result.add(b);

        return result;
    }


    public static boolean isNotNumber(String s)
    {
        Pattern p = Pattern.compile("([0-9])");
        Matcher m = p.matcher(s);
        m.find();
        try {
            m.group(1);
        } catch(Exception e) {
            return true;
        }
        return false;
    }


    public static double preliminary(String a, String b)
    {
        double result = 0;

        if(a.contains(b) && a.substring(a.indexOf(b)).equals(b)) {
            result = CODISettings.preliminaryWeight;
        }
        if(b.contains(a) && b.substring(b.indexOf(a)).equals(a)) {
            result = CODISettings.preliminaryWeight;
        }

        return result;
    }
}